package com.test.config;

import com.test.bean.Color;
import com.test.bean.ColorFactoryBean;
import com.test.bean.Person;
import com.test.bean.Red;
import com.test.condition.LinuxCondition;
import com.test.condition.MyImportBeanDefinitionRegistrar;
import com.test.condition.MyImportSelector;
import com.test.condition.WindowsCondition;
import org.springframework.context.annotation.*;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/11/27 14:30
 * <p>
 * 使用@Import导入组件，默认的id是全类名
 */
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

    /**
     * bean默认是单实例的
     * prototype:多实例的，ioc启动并不会调用方法创建对象放入容器中，每次获取对象的时候调用方法去创建对象
     * singleton：单实例(默认值),ioc容器启动会调用方法创建对象放到ioc容器中，以后每次获取就是直接从容器（map.get()）中获取
     * request：同一个请求创建一个实例
     * session：同一个session创建一个实例
     * <p>
     * 使用@Scope调整作用域
     * <p>
     * 懒加载：
     * 单实例bean，默认在容器启动的时候创建对象；
     * 懒加载，容器启动的时候不创建对象，第一次使用（获取）bean的时候创建对象并初始化
     *
     * @return
     */
    @Scope("singleton")
    @Lazy
    @Bean("person")
    public Person person() {
        System.out.println("给容器创建person实例...");
        return new Person("zhangsan", 25);
    }

    /**
     * @Conditional({Condition}) 按照一定条件进行判断，满足条件给容器中注册bean
     * 可以标记在类上，也可以标记在方法上
     * 当标记在类上的时候，只有满足了条件，类里面的配置才会生效
     * <p>
     * 如果是windows系统，则注册bill，如果linux系统，则注册linus
     */
    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person02() {
        return new Person("linus", 48);
    }

    /**
     * 给容器注册组件的方式：
     * 1.包扫描+组件标注注解，局限于自己写的类
     * 2.使用@Bean【导入的第三方包里面的组件】
     * 3.@Import【快速的给容器中导入一个组件】
     * 3.1 @Import(要导入到容器中的组件)，容器中就会自动注册这个组件，id默认是全类名
     * 3.2* ImportSelector:返回需要导入的组件的全类名的数组
     * 3.3 ImportBeanDefinitionRegistrar：手动注册bean到容器中
     * 4.使用Spring提供的FactoryBean（工厂bean）
     *  4.1 默认获取到的是工厂bean调用getObject创建的对象
     *  4.2 要获取工厂Bean本身，需要在id前加一个&
     *  &colorFactoryBean
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}
